//
//  CalendarView.swift
//  SwiftUIDemo
//
//  Created by zhouzuosong on 2020/12/25.
//  Copyright © 2020 Kael. All rights reserved.
//

import SwiftUI

fileprivate extension Date {
    private struct AssociatedKey {
        static var haveCourse: Bool = false
    }
    
    public var haveCourse: Bool {
        get {
            return objc_getAssociatedObject(self, &AssociatedKey.haveCourse) as? Bool ?? false
        }
        
        set {
            objc_setAssociatedObject(self, &AssociatedKey.haveCourse, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }
    static func getMonth (date: Date) -> Int {
        let dateFormatter = DateFormatter() // 创建一个日期格式器
        dateFormatter.dateFormat = "MM"
        let monthString = dateFormatter.string(from: date)
        return Int(monthString) ?? 1
    }
    
    func isSameDay(with date:Date) -> Bool {
        let dateFormatter = DateFormatter() // 创建一个日期格式器
        dateFormatter.dateFormat = "yyyy MMdd"
        
        let currentDateString = dateFormatter.string(from: self)
        let anotherDateString = dateFormatter.string(from: date)
        
        if currentDateString == anotherDateString {
            return true
        }
        return false
        
    }
}

fileprivate extension DateFormatter {
    static var month: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMMM"
        return formatter
    }

    static var monthAndYear: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMMM yyyy"
        return formatter
    }
}

fileprivate extension Calendar {
    func generateDates(
        inside interval: DateInterval,
        matching components: DateComponents
    ) -> [Date] {
        var dates: [Date] = []
        
        dates.append(interval.start)

        enumerateDates(
            startingAfter: interval.start,
            matching: components,
            matchingPolicy: .nextTime
        ) { date, _, stop in
            if var date = date {
                if date < interval.end {
                    if LXLiveListDataManager.haveLiveCourse(with: date) {
                        date.haveCourse = true
                        print("有课A Date:\(date.timeIntervalSince1970)")
                    }else{
                        date.haveCourse = false
                        print("没有课B Date:\(date.timeIntervalSince1970)")
                    }
                    dates.append(date)
                } else {
                    stop = true
                }
            }
        }
        
        print("\(dates.count)")
        
        return dates
    }
}

struct MonthView<DateView>: View where DateView: View {
    @Environment(\.calendar) var calendar

    let month: Date
    let content: (Date, Bool, Bool) -> DateView
    
    init(
        month: Date,
        @ViewBuilder content: @escaping (Date, Bool, Bool) -> DateView
    ) {
        self.month = month
        self.content = content
    }

    private var weeks: [Date] {
        guard
            let monthInterval = calendar.dateInterval(of: .month, for: month)
            else { return [] }
        return calendar.generateDates(
            inside: monthInterval,
            matching: DateComponents(hour: 0, minute: 0, second: 0, weekday: 1)
        )
    }

    var body: some View {
        VStack {
            ForEach(weeks, id: \.self) { week in
                WeekView(week: week, content: self.content)
            }
            
        }
    }
}

struct WeekView<DateView>: View where DateView: View {
    @Environment(\.calendar) var calendar
    @EnvironmentObject var requestModel:LXLiveListRequestModel
    @EnvironmentObject var manager: LXLiveListDataManager

    let week: Date
    let content: (Date, Bool, Bool) -> DateView

    init(
        week: Date,
        @ViewBuilder content: @escaping (Date, Bool, Bool) -> DateView
    ) {
        self.week = week
        self.content = content
    }

    private var days: [Date] {
        guard
            let weekInterval = calendar.dateInterval(of: .weekOfYear, for: week)
            else { return [] }
        return calendar.generateDates(
            inside: weekInterval,
            matching: DateComponents(hour: 0, minute: 0, second: 0)
        )
    }

    var body: some View {
        HStack {
            ForEach(days, id: \.self) { date in
                HStack {
                    if self.calendar.isDate(self.week, equalTo: date, toGranularity: .month) {
                        self.content(date, true,LXLiveListDataManager.haveLiveCourse(with: date))
                    } else {
                        self.content(date, false, LXLiveListDataManager.haveLiveCourse(with: date))
                    }
                }
            }
        }
    }
}

struct DayView: View {
    @Environment(\.calendar) var calendar
    @EnvironmentObject var requestModel: LXLiveListRequestModel

    @State var date:Date
    @State var isToday : Bool
    @State var inMonth:Bool
    @State var haveCourse:Bool

    var body: some View {
        Text("周一")
            .hidden()
            .font(.system(size: 15))
            .padding(EdgeInsets(top: 6, leading: 3, bottom: 6, trailing: 3))
            .cornerRadius(10)
            .padding(.vertical, 4)
            .overlay(
                VStack(spacing:2) {
                    ZStack {
                        Circle().fill(Color.blue)
                            .frame(width: 28, height: 28, alignment: .center)
                            .opacity(isToday ? 1 : 0)
                                     
                        Text(isToday ? "今" : String(self.calendar.component(.day, from: date)))
                            .foregroundColor(isToday ? .white : (inMonth ? .blue : .gray))
                            .font(isToday ? .system(size: 18, weight: .bold) : .system(size: 15))

                            .padding(4)

//                                        .background(isToday ? Color.blue : Color.clear)
                            .cornerRadius(16)
                            .padding(2)
                    }
                    Circle().fill(Color.blue)
                        .frame(width: 4, height: 4, alignment: .center)
                        .opacity((inMonth && date.haveCourse) ? 1 : 0)
                }
            )
    }
}

struct WeekListView: View {
    
    var body: some View {
        HStack {
            Text("周日")
                .font(.system(size: 15))
                .padding(3)
            Text("周一")
                .font(.system(size: 15))
                .padding(3)
            Text("周二")
                .font(.system(size: 15))
                .padding(3)
            Text("周三")
                .font(.system(size: 15))
                .padding(3)
            Text("周四")
                .font(.system(size: 13))
                .padding(3)
            Text("周五")
                .font(.system(size: 15))
                .padding(3)
            Text("周六")
                .font(.system(size: 15))
                .padding(3)
            
        }
    }
}

struct LXLiveRootView: View {
    @Environment(\.calendar) var calendar
    @EnvironmentObject var requestModel: LXLiveListRequestModel

    @State private var dataManager : LXLiveListDataManager?
    @State private var liveListModel : LXLiveListRequestModel?

    private var year: DateInterval {
        calendar.dateInterval(of: .year, for: Date())!
    }

    private var months: [Date] {
        calendar.generateDates(
            inside: year,
            matching: DateComponents(day: 1, hour: 0, minute: 0, second: 0)
        )
    }
    
    private var currentMonth : Date {
        let monthIndex = Date.getMonth(date: Date())
        
        return months[monthIndex-1]
    }
    private var currentMonthIndex : Int {
        Date.getMonth(date: Date())
    }
    
    init() {
        print("初始化manager")
        self.dataManager = LXLiveListDataManager.manager
        self.liveListModel = self.dataManager?.liveListModel
    }
    
    var body: some View {
        ZStack {
            Color.blue.opacity(0.2).padding(-10)
            VStack {
                
//                Button(action:{
//                    LXLiveListDataManager.getLiveListData()
//                }){
//                    Text("刷新数据按钮")
//                }
                
                Spacer()
                Text("\(currentMonthIndex)月份")
                WeekListView()
                MonthView(month: currentMonth) { date, inMonth, haveCourse in
                    DayView(date: date, isToday: date.isSameDay(with: Date()), inMonth: inMonth, haveCourse: haveCourse)
                }
                Spacer()

            }
        }
    }
    
}

struct CalendarView_Previews: PreviewProvider {
    static var previews: some View {
        LXLiveRootView()
    }
}
